
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;

import Utils.FileUtils;
import Utils.MathUtils;
import Utils.Printers;
import Utils.SortUtils;

public class Test {
	public static int num = 7;
	public static int wordCount = 13953;

	/****************** 分隔符 *******************/
	public static String LINE_SEPARATOR = "\n";
	public static String TERM_SEPARATOR = "#";

	/****************** 目录 *******************/
	// 根目录
	public static String root = "c:/weibo/";
	// 每个人的ifidf根目录
	public static String tfidfPath = Test.root + "tfidf/";
	// 每个人的df根目录
	public static String dfPath = Test.root + "df/";
	// 根目录
	public static String simPath = Test.root+"/sim/";

	// 小时目录
	public static String hourPath = Test.root + "time/hour/";
	// 天目录
	public static String dayPath = Test.root + "time/day/";
	// 周目录
	public static String weekPath = Test.root + "time/week/";
	// 周目录
	public static String monthPath = Test.root + "time/month/";

	/****************** 文件 *******************/
	// 所有人的词表
	public static String termPath = Test.root + "terms/";
	// 所有人的词表和词频和
	public static String termCountPath = Test.root + "term_count.txt";
	// 停用词表
	public static String stopPath = Test.root + "stops.txt";

	// 统计所有人的词表
	public static void compTerms(String ids[], String names[]) {
		String result = "";
		ArrayList<String> terms = new ArrayList<String>();
		for (int i = 0; i < ids.length; i++) {
			String userId = ids[i];
			String userName = names[i];
			String content = FileUtils.readFile(Test.root + "term/" + userId + "_" + userName + ".txt", "utf-8");
			String lines[] = content.split(Test.LINE_SEPARATOR);
			for (String line : lines) {
				String term = line.split(TERM_SEPARATOR)[0];
				if (!terms.contains(term)) {
					terms.add(term);
					result += term + Test.LINE_SEPARATOR;
				}
			}
		}
		FileUtils.write(Test.termPath+"terms.txt", result);
		System.out.println(terms);
	}

	// 按照词性，统计所有人的词表
	public static void compTerms(String ids[], String names[], String pos) {
		String result = "";
		ArrayList<String> terms = new ArrayList<String>();
		for (int i = 0; i < ids.length; i++) {
			String userId = ids[i];
			String userName = names[i];
			String content = FileUtils.readFile(Test.root + pos + "/" + userId + "_" + userName + ".txt", "utf-8");
			String lines[] = content.split(Test.LINE_SEPARATOR);
			for (String line : lines) {
				String term = line.split(TERM_SEPARATOR)[0];
				if (!terms.contains(term)) {
					terms.add(term);
					result += term + Test.LINE_SEPARATOR;
				}
			}
		}
		String resultPath = Test.termPath + pos + "_terms.txt";
		FileUtils.write(resultPath, result);
	}

	// 统计所有人的词表和词频和
	public static void compTermCount(String ids[], String names[]) {
		Hashtable<String, Integer> term_count = new Hashtable<String, Integer>();
		for (int i = 0; i < ids.length; i++) {
			// 构造文件名
			String userId = ids[i];
			String userName = names[i];
			String content = FileUtils.readFile(Test.root + "term/" + userId + "_" + userName + ".txt", "utf-8");

			String lines[] = content.split(Test.LINE_SEPARATOR);
			for (String line : lines) {
				// 抽取人的词和词频
				if (line.split(TERM_SEPARATOR).length != 2)
					continue;
				String term = line.split(TERM_SEPARATOR)[0];
				int count = Integer.parseInt(line.split(TERM_SEPARATOR)[1]);

				// 统计存入新的ht
				if (term_count.containsKey(term))
					term_count.put(term, term_count.get(term) + count);
				else
					term_count.put(term, count);
			}
		}
		FileUtils.writeFileHashtable(term_count, Test.termCountPath, -1);
	}

	// 统计所有人的词表和词频和
	public static void compPOSCount(String ids[], String names[], String pos) {
		Hashtable<String, Integer> posTerm_count = new Hashtable<String, Integer>();
		for (int i = 0; i < ids.length; i++) {
			// 构造文件名
			String userId = ids[i];
			String userName = names[i];
			String content = FileUtils.readFile(Test.root + pos + "/" + userId + "_" + userName + ".txt", "utf-8");
			String lines[] = content.split(Test.LINE_SEPARATOR);
			for (String line : lines) {
				// 抽取人的词和词频
				if (line.split(TERM_SEPARATOR).length != 2)
					continue;
				String term = line.split(TERM_SEPARATOR)[0];
				int count = Integer.parseInt(line.split(TERM_SEPARATOR)[1]);

				// 统计存入新的ht
				if (posTerm_count.containsKey(term))
					posTerm_count.put(term, posTerm_count.get(term) + count);
				else
					posTerm_count.put(term, count);
			}
		}
		String posTermCountPath = Test.root + pos+"_count.txt";
		FileUtils.writeFileHashtable(posTerm_count, posTermCountPath, -1);
	}

	// 为每个人生成高频词汇表，但是是百分比的形式,id_count/term_count
	public static void compTermRatio(String[] ids, String names[]) {
		Hashtable<String, Integer> term_countSum = FileUtils.readHashtableI(Test.termCountPath);
		for (int i = 0; i < ids.length; i++) {
			Hashtable<String, Double> result = new Hashtable<String, Double>();
			// 构造文件名
			String userId = ids[i];
			String userName = names[i];
			String fileName = Test.root + "term/" + userId + "_" + userName + ".txt";
			String resultName = Test.root + "term/" + userId + "_" + userName + "_ratio.txt";

			// 读取小词表，统计百分比
			Hashtable<String, Integer> term_count = FileUtils.readHashtableI(fileName);
			Enumeration<String> en = term_count.keys();
			System.out.println("词个数:" + term_count.size());
			while (en.hasMoreElements()) {
				String term = (String) en.nextElement();
				int count = term_count.get(term);
				result.put(term, (double) count / term_countSum.get(term));
			}
			FileUtils.writeFileHashtable(result, resultName, -1);
		}

	}

	// 为每个人生成高频词汇表，但是是百分比的形式,id_count/term_count
	public static void compPOSRatio(String[] ids, String names[], String pos) {
		// 所有人的词表和词频和
		String posTermCountPath = Test.root + pos+"_count.txt";
		Hashtable<String, Integer> term_countSum = FileUtils.readHashtableI(posTermCountPath);
		for (int i = 0; i < ids.length; i++) {
			Hashtable<String, Double> result = new Hashtable<String, Double>();
			// 构造文件名
			String userId = ids[i];
			String userName = names[i];
			String fileName = Test.root + pos + "/" + userId + "_" + userName + ".txt";
			String resultName = Test.root + pos + "/" + userId + "_" + userName + "_ratio.txt";

			// 读取小词表，统计百分比
			Hashtable<String, Integer> term_count = FileUtils.readHashtableI(fileName);
			Enumeration<String> en = term_count.keys();
			System.out.println("词个数:" + term_count.size());
			while (en.hasMoreElements()) {
				String term = (String) en.nextElement();
				int count = term_count.get(term);
				result.put(term, (double) count / term_countSum.get(term));
			}
			FileUtils.writeFileHashtable(result, resultName, -1);
		}

	}

	public static double[] loadVector(String fileName) {
		double[] vector = new double[Test.wordCount];
		String content = FileUtils.readFile(fileName, "utf-8");
		String lines[] = content.split(Test.LINE_SEPARATOR);
		int count = 0;
		for (String line : lines) {
			double tfidf = Double.parseDouble(line.split(Test.TERM_SEPARATOR)[1]);
			vector[count] = tfidf;
			count++;
		}
		return vector;
	}

	public static void compSimMatrix(String[] ids, String[] names) {
		String result = "";
		for (int i = 0; i < ids.length; i++) {
			for (int j = 0; j < ids.length; j++) {
				String userId1 = ids[i];
				String userName1 = names[i];
				String userId2 = ids[j];
				String userName2 = names[j];
				String fileName1 = Test.tfidfPath + userId1 + "_" + userName1 + ".txt";
				String fileName2 = Test.tfidfPath + userId2 + "_" + userName2 + ".txt";
				double v1[] = loadVector(fileName1);
				double v2[] = loadVector(fileName2);

				// 计算余弦相似度
				double sim = MathUtils.precision(MathUtils.compCos(v1, v2), 3);
				result += userName1 + "_" + userName2 + Test.TERM_SEPARATOR + sim + Test.LINE_SEPARATOR;
			}
		}
		FileUtils.write(Test.simPath+"sim.txt", result);

	}

	public static void compSimMatrix(String[] ids, String[] names, String pos) {
		String result = "";
		for (int i = 0; i < ids.length; i++) {
			for (int j = 0; j < ids.length; j++) {
				String userId1 = ids[i];
				String userName1 = names[i];
				String userId2 = ids[j];
				String userName2 = names[j];
				String fileName1 = Test.tfidfPath + userId1 + "_" + userName1 + "_" + pos + ".txt";
				String fileName2 = Test.tfidfPath + userId2 + "_" + userName2 + "_" + pos + ".txt";
				double v1[] = loadVector(fileName1);
				double v2[] = loadVector(fileName2);

				// 计算余弦相似度
				double sim = MathUtils.precision(MathUtils.compCos(v1, v2), 3);
				result += userName1 + "_" + userName2 + Test.TERM_SEPARATOR + sim + Test.LINE_SEPARATOR;
			}
		}
		String posSimPath = Test.simPath + pos + "_sim.txt";
		FileUtils.write(posSimPath, result);

	}

	public static double[][] loadSimMatrix(String fileName) {
		double matrix[][] = new double[Test.num][Test.num];
		String content = FileUtils.readFile(fileName, "utf-8");
		String lines[] = content.split("\n");
		int i = 0;
		int j = 0;
		for (String line : lines) {
			double sim = Double.parseDouble(line.split("#")[1]);
			matrix[i][j] = sim;
			j++;

			if (j % Test.num == 0) {
				i++;
				j = 0;
			}
		}
		return matrix;
	}

	// 动态聚类算法
	public static void cluster() {

		double simMatrix[][] = Test.loadSimMatrix(simPath);

		// 直接聚类法:统计所有的lamdas
		ArrayList<Double> lamdas = new ArrayList<Double>();
		for (int i = 0; i < Test.num; i++) {
			for (int j = 0; j < Test.num; j++) {
				if (!lamdas.contains(simMatrix[i][j]))
					lamdas.add(simMatrix[i][j]);
			}
		}
		// System.out.println("lamda个数:" + lamdas.size());
		lamdas = SortUtils.sortDoubleList(lamdas, -1);
		// System.out.println("排序后lamdas" + lamdas);

		// 动态聚类过程
		boolean isStop = false;
		for (Double lamda : lamdas) {
			if (isStop == true)
				break;

			int classNO = 1;
			Hashtable<String, Integer> clusters = new Hashtable<String, Integer>();
			ArrayList<Integer> clusterIds = new ArrayList<Integer>();
			for (int i = 0; i < Test.num; i++)
				for (int j = 0; j < Test.num; j++) {
					// 聚类开始
					if (simMatrix[i][j] < lamda)
						continue;
					if (i == j)
						continue;
					String iStr = String.valueOf(i);
					String jStr = String.valueOf(j);
					if (!clusters.containsKey(iStr) && !clusters.containsKey(jStr)) {
						clusters.put(iStr, classNO);
						clusters.put(jStr, classNO);
						classNO++;
					}
					if (!clusters.containsKey(iStr) && clusters.containsKey(jStr)) {
						clusters.put(iStr, clusters.get(jStr));
					}

					if (clusters.containsKey(iStr) && !clusters.containsKey(jStr)) {
						clusters.put(jStr, clusters.get(iStr));
					}
					// 聚类结束
					// 当所有的都在一个类里面，停止
					Iterator<Integer> it = clusters.values().iterator();
					while (it.hasNext()) {
						Integer clusterId = it.next();
						if (!clusterIds.contains(clusterId))
							clusterIds.add(clusterId);
					}
					if (clusterIds.size() == 1 && clusters.size() == Test.num) {
						isStop = true;
					}
				}

			System.out.println("聚类结果（" + lamda + "）:");
			Printers.htPrinters(clusters);
		}
	}

	// 动态聚类算法
	public static void cluster(String pos) {

		String posSimPath = Test.simPath + pos + "_sim.txt";
		double simMatrix[][] = Test.loadSimMatrix(posSimPath);

		// 直接聚类法:统计所有的lamdas
		ArrayList<Double> lamdas = new ArrayList<Double>();
		for (int i = 0; i < Test.num; i++) {
			for (int j = 0; j < Test.num; j++) {
				if (!lamdas.contains(simMatrix[i][j]))
					lamdas.add(simMatrix[i][j]);
			}
		}
		lamdas = SortUtils.sortDoubleList(lamdas, -1);

		// 动态聚类过程
		boolean isStop = false;
		for (Double lamda : lamdas) {
			if (isStop == true)
				break;

			int classNO = 1;
			Hashtable<String, Integer> clusters = new Hashtable<String, Integer>();
			ArrayList<Integer> clusterIds = new ArrayList<Integer>();
			for (int i = 0; i < Test.num; i++)
				for (int j = 0; j < Test.num; j++) {
					// 聚类开始
					if (simMatrix[i][j] < lamda)
						continue;
					if (i == j)
						continue;
					String iStr = String.valueOf(i);
					String jStr = String.valueOf(j);
					if (!clusters.containsKey(iStr) && !clusters.containsKey(jStr)) {
						clusters.put(iStr, classNO);
						clusters.put(jStr, classNO);
						classNO++;
					}
					if (!clusters.containsKey(iStr) && clusters.containsKey(jStr)) {
						clusters.put(iStr, clusters.get(jStr));
					}

					if (clusters.containsKey(iStr) && !clusters.containsKey(jStr)) {
						clusters.put(jStr, clusters.get(iStr));
					}
					// 聚类结束
					// 当所有的都在一个类里面，停止
					Iterator<Integer> it = clusters.values().iterator();
					while (it.hasNext()) {
						Integer clusterId = it.next();
						if (!clusterIds.contains(clusterId))
							clusterIds.add(clusterId);
					}
					if (clusterIds.size() == 1 && clusters.size() == Test.num) {
						isStop = true;
					}
				}

			System.out.println("聚类结果（" + lamda + "）:");
			Printers.htPrinters(clusters);
		}
	}

	public static String getHFTerms(String ids[], String names[]) {
		// 抽出term,n,a,v
		String termStr = "";
		for (int i = 0; i < ids.length; i++) {
			int count = 0;
			String userId = ids[i];
			String userName = names[i];
			String termFile = Test.root + "term/" + userId + "_" + userName + "_ratio.txt";
			Hashtable<String, Double> term_ratio = FileUtils.readHashtableD(termFile);

			termStr += userId + "_" + userName + "\n";
			// 构造结果字符串
			Enumeration<String> term_en = term_ratio.keys();
			while (term_en.hasMoreElements()) {
				count++;
				if (count > 100)
					break;
				String term = (String) term_en.nextElement();
				double ratio = term_ratio.get(term);
				if (ratio >= 0.8)
					termStr += term + ",";
			}
			termStr += "\n";
		}
		return termStr;
	}

	public static String getHFPOS(String ids[], String names[], String pos) {
		// 抽出term,n,a,v
		String posStr = "";
		for (int i = 0; i < ids.length; i++) {
			int count = 0;
			String userId = ids[i];
			String userName = names[i];
			String posFile = Test.root + pos + "/" + userId + "_" + userName + "_ratio.txt";
			Hashtable<String, Double> pos_ratio = FileUtils.readHashtableD(posFile);
			posStr += userId + "_" + userName + "\n";
			// 构造结果字符串
			Enumeration<String> pos_en = pos_ratio.keys();
			while (pos_en.hasMoreElements()) {
				count++;
				if (count > 100)
					break;
				String word = (String) pos_en.nextElement();
				double ratio = pos_ratio.get(word);
				if (ratio >= 0.8)
					posStr += word + ",";
			}
			posStr += "\n";
		}
		return posStr;
	}

	public static void main(String arg[]) {

	}

}
/******** 测试用的数据 **********/
// double simMatrix[][] = { { 1, 0.8, 1, 0.2, 0.8, 0.5, 0.3 }, { 0.8, 1,
// 0.4, 0.3, 0.7, 0.6, 0.3 }, { 1, 0.4, 1, 0.7, 1, 0.6, 0.5 }, { 0.4,
// 0.3, 0.7, 1, 0.5, 0.8, 0.6 }, { 0.8, 0.7, 1, 0.5, 1, 0.2, 0.7 }, {
// 0.5, 0.6, 0.6, 0.8, 0.2, 1, 0.8 },
// { 0.3, 0.3, 0.5, 0.6, 0.7, 0.8, 1 } };
